﻿// *----------------------------------------------------------------
// Copyright (C) 2017 通通优品
// 版权所有。
// 
// 类名：ApiAuthorizationAttribute.cs
// 功能描述：TongTongMall.MallWeb
// 
// Create User：jym 2017/02/09
// 
// Edit User：UserName,EditTime
// Describe：Describe
// ----------------------------------------------------------------*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Web.Http.Controllers;
using TongTongMall.Authorization;
using TongTongMall.Dependecy;
using TongTongMall.Extensions;
using TongTongMall.MallWeb.Application.Configuration.Session;
using TongTongMall.MallWeb.Core.Enums;
using TongTongMall.Oauth2._0.Client;
using TongTongMall.Oauth2._0.Server;

namespace TongTongMall.MallWeb.WebApi.Filter
{
    /// <summary>
    /// 统一登录授权/访问验证
    /// </summary>
    [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true, AllowMultiple = false)]
    public class ApiAuthorizationAttribute : UserValidateFilterAttribute
    {
        /// <summary>
        /// 
        /// </summary>
        public ApiAuthorizationAttribute() : base(IocManager.Instance.Resolve<IMallWebSession>())
        {

            OnValidateAuthorzation = (context, dic) =>
            {
                context.Response = ErrorInfo(context, dic);
            };
            OnHandleAuthorzation = (context, dic) =>
            {
                context.Response = ErrorInfo(context, dic);
            };

        }

        /// <summary>
        /// 验证错误集合
        /// </summary>
        /// <param name="context"></param>
        /// <param name="errorDic"></param>
        /// <returns></returns>
        public HttpResponseMessage ErrorInfo(HttpActionContext context, Dictionary<OAuthClientErrorStatus, string> errorDic)
        {
            var code = (int)ErrCode.Success; ;
            var errorMsg = string.Empty;
            if (errorDic.Count > 0)
            {
                var item = errorDic.FirstOrDefault();
                switch (item.Key)
                {
                    case OAuthClientErrorStatus.AccessTokenError:
                        code = (int)ErrCode.TokenErr;
                        errorMsg = "登录错误！";
                        break;
                    case OAuthClientErrorStatus.AccessTokenExpire:
                        code = (int)ErrCode.TokenExpire;
                        errorMsg = "登录失效，请重新登录！";
                        break;
                    case OAuthClientErrorStatus.UserLack:
                        code = (int)ErrCode.UserSessionLack;
                        errorMsg = "没有找到用户信息，请重新登录！";
                        break;
                    case OAuthClientErrorStatus.UserChange:
                        code = (int)ErrCode.UserInfoChange;
                        errorMsg = "用户信息发生变化，请重新登录！";
                        break;
                }
            }
            throw new AuthorizationException(code, errorMsg);
        }

        /// <summary>
        /// 是否需要登录
        /// </summary>
        public bool IsNeedLogin { get; set; } = true;

        /// <summary>
        /// 是否启用过滤器
        /// 禁用后无法保证正确获取租户信息与用户信息
        /// </summary>
        public bool IsEnable { get; set; } = true;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="actionContext"></param>
        public override void OnAuthorization(HttpActionContext actionContext)
        {
            var actionInstance = actionContext.ActionDescriptor.GetCustomAttributes<ApiAuthorizationAttribute>(true).FirstOrDefault() ?? actionContext.ActionDescriptor.ControllerDescriptor.GetCustomAttributes<ApiAuthorizationAttribute>(true).FirstOrDefault();

            if (actionInstance != null)
            {
                if (!actionInstance.IsEnable)
                {
                    return;
                }
                else
                {
                    var owinContext = OwinHttpRequestMessageExtensions.GetOwinContext(actionContext.Request);
                    bool tokenHasExpired = false;
                    if (owinContext != null)
                    {
                        tokenHasExpired = owinContext.Environment.ContainsKey(OAuthStatus.AccessToken_Expire);
                    }
                    if (tokenHasExpired && !Session.UserID.HasValue)
                    {
                        throw new AuthorizationException((int)ErrCode.PublicTokenExpire, "公共授权Token过期");
                    }
                    //判断静默授权
                    if (Session.TenantID == null || Session.Platform.IsNullOrEmpty())
                    {
                        throw new AuthorizationException((int)ErrCode.TokenErr, "AccessToken错误");
                    }
                    if (Session.TenantName.IsNullOrEmpty())
                    {
                        throw new AuthorizationException((int)ErrCode.TokenErr, "授权信息不完整，请重新授权");
                    }
                }
                if (!actionInstance.IsNeedLogin) return;
                base.OnAuthorization(actionContext);
            }
        }
    }
}